package com.java.yz.day09.ketang;

import java.util.Objects;

/*    Object中的成员方法
    public int hashCode()
    public final Class getClass()
    public String toString()
    public boolean equals(Object obj)
    protected void finalize()
    protected Object clone()
 */
class Demo2 implements Cloneable{
    int age;
    String name;
    public Demo2(){

    }
    public Demo2(int age,String name){
        this.name=name;
        this.age=age;
    }

    @Override    //这就是之前的show展示
    public String toString() {
        return "Demo2{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Demo2 demo2 = (Demo2) o;
        return age == demo2.age && name.equals(demo2.name);
    }


    @Override
    public Demo2 clone() {
        try {
            Demo2 clone = (Demo2) super.clone();
            // TODO: copy mutable state here, so the clone can't change the internals of the original
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
public class ObjectDemo2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Demo2 demo2 = new Demo2();
        //public int hashCode()
        System.out.println(demo2.hashCode());   //990368553
        //返回该对象的哈希码值。默认情况下，该方法会根据对象的地址来计算。

        //public final Class getClass()
        System.out.println(demo2.getClass());  //class com.java.yz.day09.ketang.Demo2
        //可以通过Class类中的一个方法，获取对象的真实类的全名称。

        //public String toString()
        System.out.println(demo2.toString());  //com.java.yz.day09.ketang.Demo2@3b07d329
        /*
            A:返回该对象的字符串表示。
                底层源码。
                public static String valueOf(Object obj) {
                         return (obj == null) ? "null" : obj.toString();
                    }
            B:它的值等于： 这是有getClass()和hashCode()两者的结合
                getClass().getName() + '@' + Integer.toHexString(hashCode())
            C:由于默认情况下的数据对我们来说没有意义，一般建议重写该方法。
                a:手动重写
                b:自动生成
         */

        //public boolean equals(Object obj)
        Object o = new Object();
        System.out.println(demo2.equals(o)); //false
        /*  比较的就是地址值
            A:指示其他某个对象是否与此对象“相等”。
            B:默认情况下比较的是对象的引用是否相同。
            C:由于比较对象的引用没有意义，一般建议重写该方法。
                a:手动重写
                b:自动生成
            TODO:D: == 和 equals() 的区别。(面试题)
                ==比较基本数据类型的时候，比较的是具体数值
                ==比较引用数据类型的时候，比较的是地址值
                Object中的equals（）的底层实现是有==比较的

         */

        //protected void finalize()
        /*  protect修饰
            A:当垃圾回收器确定不存在对该对象的更多引用时，由对象的垃圾回收器调用此方法。
            B:垃圾回收器不会马上回收垃圾，但是我们可以建议它尽快回收垃圾。(System.gc()方法)
            C:主要针对堆内存。
         */

        //protected Object clone()
        /*
            创建并返回此对象的一个副本，这种克隆机制十分高效，而且二者之间完全隔离。
            自定义类实现克隆步骤：
            A:自定义类实现Cloneable接口，这是一个标记性接口(相当于给了一个权限)，
            标记接口：连常量和抽象方法都没有
            实现这个接口的类的对象可以实现自我克隆。
            B:自定义类中重写Object类的clone()方法。
            C:重写clone()方法时通过super.clone()调用Object类的clone()方法来得到该对象的副本，
            并返回该副本。

            注意：
            A:克隆和两个引用指向同一个对象的区别?
            B:Object类clone()方法虽然简单，易用，
            但仅仅是一种”浅克隆”,它只克隆该对象所有的Field值，
            不会对引用类型的Field所引用的对象进行克隆。开发中，我们也可以实现对象的”深度克隆”。
         */
        Demo2 demo21 = new Demo2(18,"张三");
        Demo2 demo22 = new Demo2(18,"张三");
        System.out.println(demo21.equals(demo22)); //不重写之前就是地址值，重写之后就是比较内容
        Demo2 demo23=demo22.clone();
        System.out.println(demo23);//克隆出来的地址值不一样,Demo2{age=18, name='张三'}
    }
}
